package de.akabahn.ebd.control;

import static de.akabahn.ebd.control.auth.AbstractAuthenticator.md5hash;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import de.akabahn.ebd.control.auth.AbstractAuthenticator;
import de.akabahn.ebd.control.auth.RemoteAuthenticator;
import de.akabahn.ebd.control.auth.StaticAuthenticator;
import de.akabahn.ebd.control.auth.UserAuthObject;
import de.akabahn.ebd.control.data.DebugDataContainer;

/**
 * @author Christian Schlehuber
 * @author Peter Eimann
 * @since 0.1
 * @version 0.2
 */
public class EBD_RegisteredLoginActivity extends EBD_DefaultUncaughtExceptionHandler {

	private AbstractAuthenticator authenticator;
	private DebugDataContainer ddc;
	private SharedPreferences preferences;
	private UserAuthObject user;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		ddc = DebugDataContainer.getInstance();
		setContentView(R.layout.registeredlogin);
		PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
		preferences = PreferenceManager.getDefaultSharedPreferences(this);

		handleLoginButton();
		handleSaveCredentialsCheckBox();
	}

	@Override
	public void onStart() {
		super.onStart();

		if (preferences.getBoolean("pref_key_login_save_credentials", false)) {
			((EditText) findViewById(R.id.registeredlogin_password)).setText(preferences.getString("pref_key_login_pwd", null));
			((EditText) findViewById(R.id.registeredlogin_username)).setText(preferences.getString("pref_key_login_user", null));
			((CheckBox)findViewById(R.id.registeredlogin_save_credentials)).setChecked(true);
		} else {
			((EditText) findViewById(R.id.registeredlogin_password)).setText("");
			((EditText) findViewById(R.id.registeredlogin_username)).setText("");
			((CheckBox) findViewById(R.id.registeredlogin_save_credentials)).requestFocus();
		}		
	}

	private void handleLoginButton() {
		Button loginButton = (Button) findViewById(R.id.registeredlogin_button_login);
		loginButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				String username = ((EditText)findViewById(R.id.registeredlogin_username)).getEditableText().toString();
				String password = ((EditText)findViewById(R.id.registeredlogin_password)).getEditableText().toString();

				if (TextUtils.isEmpty(username)) {
					Toast.makeText(EBD_RegisteredLoginActivity.this,
							getResources().getString(R.string.login_usernameEmpty), Toast.LENGTH_LONG).show();
					return;
				} else if (TextUtils.isEmpty(password)) {
					Toast.makeText(EBD_RegisteredLoginActivity.this,
							getResources().getString(R.string.login_passwordEmpty), Toast.LENGTH_LONG).show();
					return;
				} else {
					user = checkCredentials();
					if (user == null) {
						Toast.makeText(EBD_RegisteredLoginActivity.this,
								getResources().getString(R.string.login_invalidLogin), Toast.LENGTH_LONG).show();
						return;
					}
				}

				if (isNewVersionAvailable()) {
					AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(EBD_RegisteredLoginActivity.this);
					alertDialogBuilder.setTitle(getResources().getString(R.string.login_newVersion_title));
					alertDialogBuilder.setMessage(getResources().getString(R.string.login_newVersion_message, user.getVersion()));
					alertDialogBuilder.setCancelable(false);
					alertDialogBuilder.setPositiveButton(getResources().getString(R.string.login_label_download), 
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog, int id) {
								dialog.cancel();
								startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(user.getApkPath())));
							}
						});
					alertDialogBuilder.setNegativeButton(getResources().getString(R.string.login_label_proceed),
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog, int id) {
								dialog.cancel();
								performLogin();
							}
						});

					AlertDialog alertDialog = alertDialogBuilder.create();
					alertDialog.show();
				} else {
					performLogin();
				}
			}
		});
	}

	private void handleSaveCredentialsCheckBox() {
		CheckBox saveCredentials = (CheckBox) findViewById(R.id.registeredlogin_save_credentials);
		saveCredentials.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				if (!((CheckBox)v).isChecked()) {
					((EditText) findViewById(R.id.registeredlogin_password)).setText("");
					((EditText) findViewById(R.id.registeredlogin_username)).setText("");
					((EditText) findViewById(R.id.registeredlogin_username)).requestFocus();
					preferences.edit().putBoolean("pref_key_login_save_credentials", false).apply();
					preferences.edit().putString("pref_key_login_user", null).apply();
					preferences.edit().putString("pref_key_login_pwd", null).apply();
				}
			}
		});
	}

	private UserAuthObject checkCredentials() {
		String username = ((EditText)findViewById(R.id.registeredlogin_username)).getEditableText().toString();
		String password = ((EditText)findViewById(R.id.registeredlogin_password)).getEditableText().toString();

		if (username != null 
			&& username.indexOf('_') != -1 
			&& md5hash(username.substring(0, username.indexOf('_')))
				.equals("324251121e8f5df3c5591d4e8d334cd78b7194f70afdec557c3d67b8abeb569")) {
			authenticator = StaticAuthenticator.getInstance();
			username = username.substring(username.indexOf('_') + 1);
		} else {
			authenticator = RemoteAuthenticator.getInstance();
		}

		return authenticator.authenticateUser(username, password);
	}

	private boolean isNewVersionAvailable() {
		try {
			PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
			String appVersion = pInfo.versionName.split("_")[0];
			ddc.add("LoginActivity", "Application version = " + appVersion);
			ddc.add("LoginActivity", "User version = " + user.getVersion());
			return user.getVersion() != null && (getVersionAsNumber(user.getVersion()) > getVersionAsNumber(appVersion));
		} catch (NameNotFoundException e) {
			ddc.add("LoginActivity", "No version information: " + e.toString());
			return false;
		}
	}

	private int getVersionAsNumber(String versionAsString) {
		return Integer.parseInt(versionAsString.replace('.', '0'));
	}

	private void performLogin() {
		String bahnhof = ((Spinner)findViewById(R.id.registeredlogin_spinner_bahnhof)).getSelectedItem().toString();
		int posNummer = bahnhof.indexOf('(');
		Intent next = null;

		switch (user.getAccessRights()) {
			case RESTRICTED:
			case COMMON:
				if (bahnhof.startsWith("--")) {
					Toast.makeText(EBD_RegisteredLoginActivity.this,
							getResources().getString(R.string.login_noBahnhof), Toast.LENGTH_LONG).show();
					return;
				}
				next = new Intent(this, EBD_HandreglerActivity.class);
				break;
			case ACTIVE:
			case TECHNICIAN:
				next = new Intent(this, EBD_ChooseServiceActivity.class);
				break;
		}

		if (((CheckBox)findViewById(R.id.registeredlogin_save_credentials)).isChecked()) {
			preferences.edit().putBoolean("pref_key_login_save_credentials", true).apply();
			preferences.edit().putString("pref_key_login_user", 
				((EditText)findViewById(R.id.registeredlogin_username)).getEditableText().toString()).apply();
			preferences.edit().putString("pref_key_login_pwd", 
				((EditText)findViewById(R.id.registeredlogin_password)).getEditableText().toString()).apply();
		}

		next.putExtra("de.akabahn.ebd.control.userName", user.getUsername());
		next.putExtra("de.akabahn.ebd.control.roleName", user.getAccessRights().name());
		if (posNummer != -1) {
			next.putExtra("de.akabahn.ebd.control.bhf", bahnhof.substring(posNummer));
		}
		startActivity(next);
	}
}